package br.usp.ime.ingpos.services;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import br.com.caelum.vraptor.core.Localization;
import br.com.caelum.vraptor.ioc.Component;
import br.com.caelum.vraptor.ioc.RequestScoped;
import br.usp.ime.ingpos.modelo.Candidato;
import br.usp.ime.ingpos.modelo.CartaDeRecomendacao;
import br.usp.ime.ingpos.modelo.Email;
import br.usp.ime.ingpos.modelo.Inscricao;
import br.usp.ime.ingpos.modelo.TipoProcessoSeletivo;
import br.usp.ime.ingpos.modelo.Usuario;
import br.usp.ime.ingpos.modelo.dao.CartaDeRecomendacaoDAO;
import br.usp.ime.ingpos.seguranca.Criptografia;
import br.usp.ime.ingpos.web.controllers.UsuarioSessao;

@RequestScoped
@Component
public class CartaDeRecomendacaoService
{

    private final CartaDeRecomendacaoDAO cartaDeRecomendacaoDAO;
    private final UsuarioSessao usuarioSessao;
    private final EmailService emailService;
    private final InscricaoService inscricaoService;
    private final HttpServletRequest httpServletRequest;
    private final Localization localization;

    public CartaDeRecomendacaoService(
        final CartaDeRecomendacaoDAO cartaDeRecomendacaoDAO,
        final UsuarioSessao usuarioSessao,
        final EmailService emailService,
        final InscricaoService inscricaoService,
        final HttpServletRequest httpServletRequest,
        final Localization localization)
    {
        this.cartaDeRecomendacaoDAO = cartaDeRecomendacaoDAO;
        this.usuarioSessao = usuarioSessao;
        this.emailService = emailService;
        this.inscricaoService = inscricaoService;
        this.httpServletRequest = httpServletRequest;
        this.localization = localization;
    }

    public void salvarOuAtualizar(
        final CartaDeRecomendacao cartaDeRecomendacao )
    {
        cartaDeRecomendacaoDAO.saveOrUpdate( cartaDeRecomendacao );
    }

    public void solicitarRecomendacao(
        final CartaDeRecomendacao cartaDeRecomendacao )
    {
        try {
            final String hash = Criptografia.md5( cartaDeRecomendacao.getEmail()
                + usuarioSessao.getUsuario().getEmail() );

            cartaDeRecomendacao.setUsuario( usuarioSessao.getUsuario() );
            cartaDeRecomendacao.setDataDeEnvio( new Date() );
            cartaDeRecomendacao.setHash( hash );

            final CartaDeRecomendacao cartaDeRecomendacaoExistente = cartaDeRecomendacaoDAO.procurarPorHash( hash );
            if( cartaDeRecomendacaoExistente == null ) {
                cartaDeRecomendacaoDAO.saveOrUpdate( cartaDeRecomendacao );
            } else {
                cartaDeRecomendacaoExistente.setNome( cartaDeRecomendacao.getNome() );
                cartaDeRecomendacaoExistente.setDataDeEnvio( new Date() );
                cartaDeRecomendacaoDAO.saveOrUpdate( cartaDeRecomendacaoExistente );
            }

            emailService.enviarEmail( emailService.construirEmail(
                localization.getMessage( "cadastro_recomendacao_email_msg_assunto" ),
                construirConteudoCartaRecomendacao( cartaDeRecomendacao )+localization.getMessage( "email_rodape"),
                cartaDeRecomendacao.getEmail() ) );

        } catch( EmailException e ) {
            e.printStackTrace();
            throw new IllegalStateException( "Nao conseguiu enviar email" );
        }
    }

    public void reenviarRecomendacao(
        CartaDeRecomendacao cartaDeRecomendacaoParamId )
    {
        try {
            final CartaDeRecomendacao cartaDeRecomendacaoExistente = cartaDeRecomendacaoDAO.findById( cartaDeRecomendacaoParamId.getCartaDeRecomendacaoID() );

            if( cartaDeRecomendacaoExistente == null ) {
                // TODO: Erro
                throw new IllegalStateException( "Recomendacao id="
                    + cartaDeRecomendacaoParamId.getCartaDeRecomendacaoID() + " nao existe!" );

            } else {
                cartaDeRecomendacaoExistente.setDataDeEnvio( new Date() );

                cartaDeRecomendacaoDAO.saveOrUpdate( cartaDeRecomendacaoExistente );

                final Email email = emailService.construirEmail(
                    localization.getMessage( "cadastro_recomendacao_email_msg_assunto" ),
                    construirConteudoCartaRecomendacao( cartaDeRecomendacaoExistente )+localization.getMessage( "email_rodape"),
                    cartaDeRecomendacaoExistente.getEmail() );

                emailService.enviarEmail( email );

            }
        } catch( EmailException e ) {
            e.printStackTrace();
            throw new IllegalStateException( "Nao conseguiu enviar email" );
        }

    }

    public CartaDeRecomendacao procurarPorHash(
        final String hash )
    {
        return cartaDeRecomendacaoDAO.procurarPorHash( hash );
    }

    public List<CartaDeRecomendacao> procurarPorUsuario(
        final Usuario usuario )
    {
        return cartaDeRecomendacaoDAO.procurarPorUsuario( usuario );
    }

    private String construirConteudoCartaRecomendacao(
        CartaDeRecomendacao cartaDeRecomendacao )
    {
        final StringBuilder linkBuilder = new StringBuilder();

        linkBuilder.append( getUrlRecomendacao() );
        linkBuilder.append( "/dadosRecomendacao/" );
        linkBuilder.append( cartaDeRecomendacao.getHash() );

        final String urlHref = linkBuilder.toString();

        Inscricao inscricao = inscricaoService.getInscricaoAtual(null );
        final TipoProcessoSeletivo tipoProcesso = inscricao.getProcessoSeletivo().getTipoProcessoSeletivo();
        final String nomeCandidato = cartaDeRecomendacao.getUsuario().getDadosPessoais().getNomeCompleto();
        final String emailCandidato = cartaDeRecomendacao.getUsuario().getEmail();
        final String curso = localization.getMessage( "computacao" );
        final Date data = inscricao.getProcessoSeletivo().getDataLimiteDeInscricao();

        String conteudo = localization.getMessage( "cadastro_recomendacao_email_msg_conteudo",
            cartaDeRecomendacao.getNome(), nomeCandidato, emailCandidato,
            tipoProcesso.getMsgKey(), curso ,urlHref, data );

        return conteudo;
    }
    
    private String construirConteudoConfirmacaoRecomendacaoProfessor(CartaDeRecomendacao cartaDeRecomendacao){
        String conteudo = localization.getMessage( "email_confirmacao_recomendacao_professor_mensagem",
            cartaDeRecomendacao.getNome(), cartaDeRecomendacao.getUsuario().getDadosPessoais().getNomeCompleto());

        return conteudo;
    }
    
    private String construirConteudoConfirmacaoRecomendacaoAluno(CartaDeRecomendacao cartaDeRecomendacao){
        String conteudo = localization.getMessage( "email_confirmacao_recomendacao_aluno_mensagem",
            cartaDeRecomendacao.getUsuario().getDadosPessoais().getNomeCompleto(), cartaDeRecomendacao.getNome());

        return conteudo;
    }

    private String getUrlRecomendacao()
    {
        final String urlRegistro;
        if( httpServletRequest == null ) {
            // TODO: Verificar como remover esta url para efeito de testes
            urlRegistro = "http://localhost:8080/Ingresso-na-Pos/cartaRecomendacao/solicitarRecomendacao";
        } else {
            final String url = httpServletRequest.getRequestURL().toString();

            int idxDelete = url.lastIndexOf( "/solicitarRecomendacao" );
            idxDelete = idxDelete < 0 ? url.lastIndexOf( "/reenviarRecomendacao" ) : idxDelete;

            urlRegistro = url.substring( 0, idxDelete );
        }

        return urlRegistro;
    }

    public void copiaDados(
        CartaDeRecomendacao origem,
        CartaDeRecomendacao destino )
    {
        destino.setAnoObtencao( origem.getAnoObtencao() );
        destino.setAntecedentesAcademicos( origem.getAntecedentesAcademicos() );
        destino.setAproveitamentoSeAceito( origem.getAproveitamentoSeAceito() );
        destino.setAreaProfessor( origem.getAreaProfessor() );
        destino.setCargoQueOcupa( origem.getCargoQueOcupa() );
        destino.setContextoCategoriaCantidato( origem.getContextoCategoriaCantidato() );
        destino.setCursoCandidato( origem.getCursoCandidato() );
        destino.setEmail( origem.getEmail() );
        destino.setEnderecoCorrespondencia( origem.getEnderecoCorrespondencia() );
        destino.setGrauAcademicoMaisAlto( origem.getGrauAcademicoMaisAlto() );
        destino.setInstituicao( origem.getInstituicao() );
        destino.setInstituicaoObteveGrau( origem.getInstituicaoObteveGrau() );
        destino.setNome( origem.getNome() );
        destino.setOutraCondicaoConheceCandidato( origem.getOutraCondicaoConheceCandidato() );
        destino.setOutrasInformacoes( origem.getOutrasInformacoes() );
        destino.setTempoConheceCandidato( origem.getTempoConheceCandidato() );
        destino.setTipoCategoriaCandidato( origem.getTipoCategoriaCandidato() );
        destino.setTipoConheceCandidato( origem.getTipoConheceCandidato() );
    }
    
    public boolean cartaDeRecomendacaoRecebidas(){
        List<CartaDeRecomendacao> cartas = procurarPorUsuario( usuarioSessao.getUsuario() );
        if(cartas.size() < 2)
            return false;
        return true;
        
    }

    public void enviarCartaConfirmacaoRecebimento(
        CartaDeRecomendacao cartaDeRecomendacao )
    {
        try {
                final Email email = emailService.construirEmail(
                    localization.getMessage( "email_confirmacao_recomendacao_professor_assunto" ),
                    construirConteudoConfirmacaoRecomendacaoProfessor( cartaDeRecomendacao )+localization.getMessage( "email_rodape"),
                    cartaDeRecomendacao.getEmail() );

                emailService.enviarEmail( email );

        } catch( EmailException e ) {
            e.printStackTrace();
            throw new IllegalStateException( "Nao conseguiu enviar email para professor" );
        }
        
        try {
            final Email email = emailService.construirEmail(
                localization.getMessage( "email_confirmacao_recomendacao_aluno_assunto" ),
                construirConteudoConfirmacaoRecomendacaoAluno( cartaDeRecomendacao )+localization.getMessage( "email_rodape"),
                cartaDeRecomendacao.getUsuario().getEmail() );

            emailService.enviarEmail( email );

    } catch( EmailException e ) {
        e.printStackTrace();
        throw new IllegalStateException( "Nao conseguiu enviar email para aluno" );
    }
        
    }
}
